import React, {useState} from "react";
import {
    DeviceEventEmitter,
    Image,
    Pressable,
    SafeAreaView,
    Text,
    useWindowDimensions,
    View
} from "react-native";
import {CheckBox, Icon} from "@rn-vui/themed";
import {useThemeColors} from "../hooks/hooks.tsx";
import ApiService from "../../utils/ApiService";
import useStyles from "./useStyles.tsx";
import DialogProcesser from "./components/DialogProcesser.tsx";
import {OrderColorMap, OrderStatusMap} from "./components/OrderTypes.tsx";
import DialogRestore from "./components/DialogRestore.tsx";
import {DateTimePickerAndroid, DateTimePickerEvent} from '@react-native-community/datetimepicker';
import OrderColumn from "./components/OrderColumn.tsx";
import DialogNote from "./components/DialogNote.tsx";
import Confirm from "../components/Confirm.tsx";
import echo from "../../utils/echo.tsx";
import {FlashList} from "@shopify/flash-list";
import DialogSettings from "./components/DialogSettings.tsx";
import Toast from "../components/Toast.tsx";
import AsyncStorage from "@react-native-async-storage/async-storage";
import TcpServer from "./utils/TcpServer.tsx";
import TcpClient from "./utils/TcpClient.ts";
import DeviceInfo from "react-native-device-info";
import Sound from "react-native-sound";
import * as types from '../../store/types';

const limit = 6;
const PilotIndex = ({navigation}: any) => {
    const styles = useStyles();
    const colors = useThemeColors();
    const w = useWindowDimensions().width / 6;
    const [isHomeScreen, setIsHomeScreen] = useState<boolean>(true);
    const [orders, setOrders] = useState<any>([]);
    const [total, setTotal] = useState<number>(0);
    const [stats, setStats] = useState<any>({
        total: 0,
        pending: 0,
        done: 0,
        holdon: 0,
        cancelled: 0
    });
    const [selectedOrders, setSelectedOrders] = useState<any[]>([]);
    const [multipel, setMultipel] = useState<boolean>(false);
    const [currentOrder, setCurrentOrder] = useState<any>({});
    const [offsetIndex, setOffsetIndex] = useState<number>(0);
    const [dishStatus, setDishStatus] = useState<string>('');
    const [columnCount, setColumnCount] = useState<number>(6);
    const [contentHeight, setContentHeight] = useState<number>(500);
    const processer = React.useRef<any>(null);
    const restoreRef = React.useRef<any>(null);
    const noteRef = React.useRef<any>(null);
    const scrollRef = React.useRef<any>(null);
    const settingsRef = React.useRef<any>(null);
    const fullOrders = React.useRef<any>([]);
    const tcpClient = React.useRef<any>(null);
    const tcpServer = React.useRef<any>(null);
    const deviceId = React.useRef<string>();
    const soundRef = React.useRef<any>(null);
    const dishStatusRef = React.useRef<string>(dishStatus);

    const loadData = React.useCallback(() => {
        Promise.all([
            ApiService.get("/pilot/orders", {
                params: {
                    offset: 0,
                    limit: 50
                }
            }),
            ApiService.get('/pilot/orders/stats')
        ]).then(values => {
            const {total, items} = values[0].data;
            fullOrders.current = items;
            setTotal(total);
            //console.log('items:', items);
            //console.log('dishStatus:', dishStatusRef.current);
            if (dishStatusRef.current === '') {
                setOrders([...items]);
            } else {
                setOrders(items.filter((item: any) => item.dish_status === dishStatusRef.current));
            }
            setStats({
                pending: 0,
                done: 0,
                holdon: 0,
                takeout: 0,
                cancelled: 0,
                ...values[1].data
            });
        }).catch(reason => {
            console.error(reason.message);
        });
    }, [dishStatus]);

    const chooseOrder = (order: any) => {
        setCurrentOrder({...order});
        if (order.dish_status === 'holdon') {
            restoreRef.current?.open(() => {
                ApiService.put(`/pilot/orders/${order.id}`, {dish_status: 'pending'}).then(() => {
                    loadData();
                });
            });
        } else {
            processer.current?.open(order, (dish_status: string) => {
                if (dish_status === 'holdon') {
                    openDateTimePicker(order);
                } else if (order.dish_status === 'done') {
                    Confirm.show({
                        onConfirm: () => {
                            ApiService.put(`/pilot/orders/${order.id}`, {
                                dish_status
                            }).then(response => {
                                //console.log(response.data);
                            }).catch(reason => {
                                console.error(reason.message);
                            }).finally(() => {

                            });
                        }
                    });
                } else {
                    ApiService.put(`/pilot/orders/${order.id}`, {
                        dish_status
                    }).then(response => {
                        //console.log(response.data);
                    }).catch(reason => {
                        console.error(reason.message);
                    }).finally(() => {

                    });
                }
            });
        }
    }

    const goPrevPage = () => {
        if (offsetIndex > 0) {
            setOffsetIndex(prev => {
                sendData(prev - 1);
                return prev - 1;
            });
        }
    }

    const goNextPage = () => {
        if (offsetIndex < columnCount - 2) {
            setOffsetIndex(prev => {
                sendData(prev + 1);
                return prev + 1;
            });
        }
    }

    const goFirstPage = () => {
        sendData(isHomeScreen ? 0 : 6);
        setOffsetIndex(isHomeScreen ? 0 : 6);
    }

    const goLastPage = () => {
        if (columnCount > 0) {
            sendData(columnCount - 2);
            setOffsetIndex(columnCount - 2);
        }
    }

    const onMomentumScrollEnd = (event: any) => {
        // scrollRef.current.scrollToIndex({
        //     index: 1,
        //     animated: false
        // });
    }

    const onSelectOrder = (order: any) => {
        if (multipel) {
            if (selectedOrders.includes(order)) {
                setSelectedOrders(selectedOrders.filter(item => item.id !== order.id));
            } else {
                setSelectedOrders([...selectedOrders, order]);
            }
        }
    }

    const onStickyOrders = () => {
        if (selectedOrders.length) {
            ApiService.post('/pilot/orders/sticky', {
                ids: selectedOrders.map(item => item.id)
            }).then(() => {

            }).finally(() => {
                setMultipel(false);
                setSelectedOrders([]);
            });
        }
    }

    const onDeleteOrders = () => {
        if (selectedOrders.length > 0) {
            Confirm.show({
                title: '删除订单',
                message: '确定要删除所选订单吗？',
                onConfirm: () => {
                    ApiService.delete('/pilot/orders/batch', {
                        data: {
                            ids: selectedOrders.map(item => item.id)
                        }
                    }).then(() => {

                    }).finally(() => {
                        setMultipel(false);
                        setSelectedOrders([]);
                    });
                },
                onCancel: () => {

                }
            });
        } else {
            navigation.navigate('OrderList', {
                status: 'cancelled',
                title: '已删除的订单'
            });
        }
    }

    const openDateTimePicker = (order: any) => {
        DateTimePickerAndroid.open({
            value: new Date(),
            onChange: (event, date) => {
                //console.log('event', event);
                //console.log(date?.getHours() + ':' + date?.getMinutes());

                if (event.type === 'set') {
                    const dish_time = date?.getHours() + ':' + date?.getMinutes();
                    ApiService.put(`/pilot/orders/${order.id}`, {
                        dish_status: 'holdon',
                        dish_time: dish_time
                    }).then(response => {
                        //console.log(response.data);
                    }).catch(reason => {
                        console.error(reason.message);
                    }).finally(() => {

                    });
                }
            },
            mode: 'time',
            is24Hour: true
        });
    }

    const markOrder = (order: any) => {
        setOrders((prevOrders: any[]) => (
            prevOrders.map((item: any) => {
                if (item.id === order.id) {
                    return {
                        ...item,
                        dish_marked: !item.dish_marked
                    }
                }
                return item;
            })
        ));
        ApiService.post(`/pilot/orders/${order.id}/mark`).then(response => {
            //console.log(response.data);
        }).catch(reason => {
            console.error(reason.message);
        });
    }

    const onShowSettings = () => {
        settingsRef.current?.open((options: any) => {
            closeTcp();
            setIsHomeScreen(options.isHomeScreen);
            if (options.isHomeScreen) {
                createTcpServer();
            } else {
                createTcpClient(options.ip);
            }
        });
    }

    const getBackgroundColor = (order: any) => {
        if (order.status === 'cancelled') {
            return 'rgba(250, 182, 182,0.75)';
        }
        return colors.black;
    }

    const showNote = (order: any) => {
        noteRef.current?.open(order.buyer_note, () => {

        });
    }

    const listenData = (buf: any) => {
        try {
            const data = buf.toString();
            //console.log('listenData', data);
            const e = JSON.parse(data);
            if (e && e.type === 'sync' && e.deviceId !== deviceId.current) {
                if (e.isHomeScreen) {
                    setOffsetIndex(e.offset + 6);
                } else {
                    const startIndex = Math.max(0, e.offset - 6);
                    setOffsetIndex(startIndex);
                }
                setDishStatus(e.dishStatus);
            }
        } catch (e: any) {
            console.log(e.message);
            Toast.fail(e.message);
        }
    }

    const sendData = (offset: number) => {
        //console.log('tcpClient', tcpClient.current);
        if (isHomeScreen) {
            tcpServer.current?.send(JSON.stringify({
                type: 'sync',
                offset: offset,
                dishStatus: dishStatus,
                isHomeScreen: true,
                deviceId: deviceId.current
            }));
        } else {
            tcpClient.current?.send(JSON.stringify({
                type: 'sync',
                offset: offset,
                dishStatus: dishStatus,
                isHomeScreen: false,
                deviceId: deviceId.current
            }));
        }
    }

    const createTcpServer = () => {
        const server = new TcpServer();
        server.on('server:ready', ({port}) => {
            Toast.success('主机已成功启动！');
        });
        server.on('client_connected', () => sendData(offsetIndex));
        server.on('data', listenData);
        server.on('error', (e) => console.warn('A server error:', e));
        server.start();

        tcpServer.current = server;
    }

    const createTcpClient = (host: string) => {
        const client = new TcpClient(host);
        client.on('connect', () => {
            Toast.success('已成功连接到主机' + host);
        })
        client.on('data', listenData);
        client.start();
        tcpClient.current = client;
    }

    const closeTcp = () => {
        tcpServer.current?.stop();
        tcpClient.current?.stop();
    }

    const playVoice = React.useCallback(() => {
        AsyncStorage.getItem(types.PLAY_ORDER_SOUND).then(value => {
            if (value === 'true') {
                soundRef.current?.play();
            }
        });
    }, []);

    React.useLayoutEffect(() => {
        navigation.setOptions({
            headerShown: false,
        });
        const listener = DeviceEventEmitter.addListener('ordersDidChanged', loadData);
        //echo.register('ordersDidChanged');
        const channle = echo.channel('noodlebox')
            .stopListening('.pusher:subscription_succeeded')
            .listen('.pusher:subscription_succeeded', (e: any) => {
                console.log('pusher:subscription_succeeded');
            }).stopListening('.order.created')
            .listen('.order.created', (e: any) => {
                loadData();
                playVoice();
            }).stopListening('.order.updated')
            .listen('.order.updated', (e: any) => {
                console.log('order.updated', e);
                loadData();
            }).stopListening('.order.deleted')
            .listen('.order.deleted', (e: any) => {
                console.log('order.deleted', e);
                loadData();
            }).stopListening('.pilot.order.changed')
            .listen('.pilot.order.changed', (e: any) => {
                console.log('pilot.order.changed', e);
                loadData();
            });

        return () => {
            listener.remove();
            channle.stopListeningToAll();
        }
    }, []);

    React.useEffect(() => {
        const music = require('./assets/yd.wav');
        soundRef.current = new Sound(Image.resolveAssetSource(music).uri, "", (error) => {
            if (error) {
                console.log('failed to load the sound', error);
            } else {
                //console.log('duration in seconds: ' + sound.getDuration() + 'number of channels: ' + sound.getNumberOfChannels());
            }
        });

        closeTcp();
        Promise.all([
            AsyncStorage.getItem('isHomeScreen'),
            AsyncStorage.getItem('serverip'),
            DeviceInfo.getUniqueId()
        ]).then((values) => {
            setIsHomeScreen(values[0] === 'true');
            if (values[0] === 'true') {
                createTcpServer();
                setOffsetIndex(0);
            } else {
                setOffsetIndex(6);
                if (values[1]) createTcpClient(values[1]);
            }

            if (values[2]) {
                deviceId.current = values[2];
            }
        });

        loadData();

        return () => {
            closeTcp();
            soundRef.current?.release();
        }
    }, []);

    React.useEffect(() => {
        if (!multipel) setSelectedOrders([]);
    }, [multipel]);

    React.useEffect(() => {
        //console.log('offsetIndex', offsetIndex);
        scrollRef.current.scrollToOffset({
            offset: offsetIndex * w,
            animated: true
        });
    }, [offsetIndex, isHomeScreen, orders]);

    React.useEffect(() => {
        sendData(isHomeScreen ? 0 : 6);
        setOffsetIndex(isHomeScreen ? 0 : 6);
        setOrders(fullOrders.current.filter((item: any) => item.dish_status === dishStatus));
        dishStatusRef.current = dishStatus;
    }, [dishStatus]);

    return (
        <SafeAreaView style={{flex: 1}}>
            <View style={{flex: 1}} onLayout={e => {
                setContentHeight(e.nativeEvent.layout.height);
            }}>
                <FlashList
                    ref={scrollRef}
                    data={orders.concat([{}, {}, {}, {}, {}, {}])}
                    renderItem={({item, index}) => {
                        if (item.id) {
                            return (
                                <OrderColumn
                                    order={item}
                                    style={{backgroundColor: getBackgroundColor(item)}}
                                    onSelectOrder={onSelectOrder}
                                    onChooseOrder={chooseOrder}
                                    onMarkOrder={markOrder}
                                    onPressNote={showNote}
                                    checked={selectedOrders.includes(item)}
                                    selected={currentOrder.id === item.id}
                                    number={index + 1}
                                />
                            )
                        } else {
                            return (
                                <View style={{width: w, height: '100%', minHeight: 300}}></View>
                            )
                        }
                    }}
                    keyExtractor={(item: any, index: number) => 'order-' + index}
                    showsHorizontalScrollIndicator={false}
                    scrollEnabled={false}
                    horizontal={true}
                    removeClippedSubviews={true}
                    onMomentumScrollEnd={onMomentumScrollEnd}
                    estimatedItemSize={w}
                    onContentSizeChange={(width, h) => {
                        const columns = Math.ceil(width / w);
                        if (columns > 6) {
                            setColumnCount(columns - 6);
                        }
                    }}
                    scrollEventThrottle={16}
                    extraData={{contentHeight}}
                    overrideProps={{
                        style: {flex: 1, minHeight: contentHeight, minWidth: '100%'}
                    }}
                />
            </View>
            <View style={styles.footer}>
                {
                    isHomeScreen ? (
                        <>
                            <Pressable
                                style={[styles.button, offsetIndex === 0 && styles.buttonDisabled]}
                                onPress={() => goPrevPage()}
                                onLongPress={goFirstPage}
                            >
                                <Icon
                                    type={'entypo'}
                                    name={'arrow-bold-left'}
                                    size={40}
                                    color={colors.white}
                                />
                            </Pressable>
                            <Pressable
                                style={[styles.button, offsetIndex > (columnCount - 3) && styles.buttonDisabled]}
                                onPress={() => goNextPage()}
                                onLongPress={goLastPage}
                            >
                                <Icon
                                    type={'entypo'}
                                    name={'arrow-bold-right'}
                                    size={40}
                                    color={colors.white}
                                />
                            </Pressable>
                            <View style={styles.separator}/>
                        </>
                    ) : null
                }
                <Pressable
                    style={[styles.button, dishStatus === 'pending' && styles.buttonActive]}
                    onPress={() => setDishStatus('pending')}
                >
                    <Text style={styles.buttonText}>{'等待中'}</Text>
                    <View style={styles.badge}>
                        <Text style={styles.badgeText}>{stats.pending}</Text>
                    </View>
                </Pressable>
                <Pressable
                    style={[styles.button, dishStatus === 'done' && styles.buttonActive]}
                    onPress={() => setDishStatus('done')}
                >
                    <Text style={styles.buttonText}>{'已做完'}</Text>
                    <View style={styles.badge}>
                        <Text style={styles.badgeText}>{stats.done}</Text>
                    </View>
                </Pressable>
                <View style={styles.separator}/>
                {
                    isHomeScreen ? (
                        <Pressable
                            style={styles.button}
                            onPress={() => navigation.navigate('OrderList', {
                                status: 'takeout',
                                title: '已打包'
                            })}
                        >
                            <Text style={styles.buttonText}>{'已打包'}</Text>
                            <View style={styles.badge}>
                                <Text style={styles.badgeText}>{stats.takeout}</Text>
                            </View>
                        </Pressable>
                    ) : null
                }
                <Pressable
                    style={[styles.button, dishStatus === 'holdon' && styles.buttonActive]}
                    onPress={() => setDishStatus('holdon')}
                >
                    <Icon
                        type={'font-awesome'}
                        name={'clock-o'}
                        size={32}
                        color={colors.white}
                    />
                    <View style={styles.badge}>
                        <Text style={styles.badgeText}>{stats.holdon}</Text>
                    </View>
                </Pressable>
                <View style={styles.separator}/>
                <CheckBox
                    checked={multipel}
                    containerStyle={[styles.button, {marginVertical: 0, marginRight: 0}]}
                    onPress={() => setMultipel(!multipel)}
                    checkedColor={colors.white}
                />
                <Pressable style={styles.button} onPress={onStickyOrders}>
                    <Text style={styles.buttonText}>置顶</Text>
                </Pressable>
                <Pressable style={styles.button} onPress={onDeleteOrders}>
                    <Text style={styles.buttonText}>删除</Text>
                    <View style={styles.badge}>
                        <Text style={styles.badgeText}>{stats.cancelled}</Text>
                    </View>
                </Pressable>
                <Pressable style={styles.button} onPress={onShowSettings}>
                    <Icon name={'settings'} color={colors.white}/>
                </Pressable>
            </View>
            <DialogProcesser ref={processer}/>
            <DialogRestore ref={restoreRef}/>
            <DialogNote ref={noteRef}/>
            <DialogSettings ref={settingsRef}/>
        </SafeAreaView>
    );
};

export default PilotIndex;
